/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean.SOP;

import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import merlion.common.util.exception.NotExistException;
import merlion.crm.slcm.entity.Customer;
import merlion.crm.slcm.entity.MemberDiscountGroup;
import merlion.crm.slcm.entity.OrderDiscountGroup;
import merlion.crm.slcm.entity.SalesLead;
import merlion.crm.slcm.session.SLCSessionBeanLocal;
import merlion.crm.sopm.entity.ItemLine;
import merlion.crm.sopm.entity.SalesQuotation;
import merlion.crm.sopm.session.SOPSessionBeanLocal;
import merlion.mrp.ppm.entity.Product;
import javax.faces.context.FacesContext;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedProperty;
import managedbean.Workspace.FileUploadManagerBean;
import merlion.common.entity.Staff;
import merlion.common.session.stateless.GlobalVariableSessionBeanLocal;
import merlion.common.util.Consts;
import merlion.crm.slcm.entity.Address;
import merlion.crm.slcm.entity.ContactRecord;
import merlion.mrp.atpm.session.ATPSessionBeanLocal;
import merlion.scm.lcm.entity.DeliveryOrder;
import merlion.scm.lcm.session.LogisticControlSessionBeanLocal;
import org.primefaces.context.RequestContext;

/**
 *
 * @author Zhou Hong
 */
@ManagedBean(name = "sqManagerBean")
@ViewScoped
public class SalesQuotationManagerBean {

    public static final String SQ = "SQ";
    public static final String RESULT1 = "RESULT2";
    public static final String CUR = "CUR";
    public static final String NEWORDER = "NEWORDER";
    public static final String NEWORDER2 = "NEWORDER2";
    @ManagedProperty(value = "#{fileUploadManagerBean}")
    private FileUploadManagerBean fileManagerBean;
    @EJB
    private SOPSessionBeanLocal sOPSessionBean;
    @EJB
    private SLCSessionBeanLocal sLCSessionBean;
    @EJB
    private ATPSessionBeanLocal atpSessionBean;
    @EJB
    private LogisticControlSessionBeanLocal lcSessionBean;
    @EJB
    private GlobalVariableSessionBeanLocal gvSessionBean;
    private SalesQuotation salesQuotation;
    private SalesLead salesLead;
    private DeliveryOrder newDeliveryOrder;
    private DeliveryOrder newDeliveryOrder2;
    private ItemLine newItemLine;
    private DeliveryOrder selectedDeliveryOrder;
    private Address newAddress;
    private boolean updateMode;
    private String rfqNumber;
    private String sqNumber;
    private String leadTime;
    private String currency;
    private Double memberDiscount;
    private OrderDiscountGroup orderDiscountGroup;
    private Double subtotal;
    private Double totalDisplay;
    private Double subtotalSum;
    private Double subtotalSumDisplay;
    private Double itemSubtotal;
    private Double itemSubtotalDisplay;
    private String result;
    private String errorMsg;
    private Collection<Double> subtotals = new ArrayList<Double>();
    private Collection<OrderDiscountGroup> orderDiscountGroups = new ArrayList<OrderDiscountGroup>();
    private static final SimpleDateFormat formatter = new SimpleDateFormat("MMMMM dd, yyyy");
    private Date date1;
    private Date date2;
    private Double maxSpecialDiscount;
    
    //--------------------------------------------------------------------------
    //                              Constructor
    //--------------------------------------------------------------------------
    public SalesQuotationManagerBean() {
        subtotalSum = 0.00;
        newAddress = new Address();
        salesLead = new SalesLead();
    }

    @PostConstruct
    public void init() {
        
        maxSpecialDiscount = gvSessionBean.getGlobalVariableByKey(Consts.GLOBAL_SPECIAL_DISCOUNT).getDoubleValue().doubleValue();

        SalesQuotation sq = (SalesQuotation) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(SQ);
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(SQ);

        if (sq == null) {
            // New Create
            salesQuotation = new SalesQuotation();
            salesQuotation.setSqNumber(sOPSessionBean.generateSalesQuotationId());
            createNewItemLines();
            createNewDeliveryOrder();
            createNewDeliveryOrder2();
            salesQuotation.setCustomerExecutive((Staff) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("app.user.name"));
        } else {

            salesQuotation = sq;

            if (salesQuotation.getTotal() != (double) 0.0) {
                // If edit
                Collection<DeliveryOrder> list = salesQuotation.getDeliveryOrders();
                Iterator iter = list.iterator();
                newDeliveryOrder = (DeliveryOrder) iter.next();
                if (iter.hasNext()) {
                    newDeliveryOrder2 = (DeliveryOrder) iter.next();
                }

            } else {
                // If create next
                setDeliveryOrder();
            }
        }
    }

    //--------------------------------------------------------------------------
    //                    Sales Quotation Manager Bean Methods
    //--------------------------------------------------------------------------
    private double roundFourDecimals(double d) {
        DecimalFormat fourDForm = new DecimalFormat("#.####");
        return Double.valueOf(fourDForm.format(d));
    }

    public Collection<Product> getAllProduct() {
        return sLCSessionBean.getAllProduct();
    }

    private void createNewItemLines() {

        Collection<ItemLine> itemLines = new ArrayList<ItemLine>();
        salesQuotation.setItemLines(itemLines);

        //Add itemline for all products
        Collection<Product> products = sLCSessionBean.getAllProduct();
        for (Product pd : products) {
            ItemLine il = new ItemLine();
//            il.setWarehouse(null);
            il.setProduct(pd);
            itemLines.add(il);
        }
    }

    public void setDeliveryOrder() {

        //if full shipment
        if (salesQuotation.getFullShipment()) {

            Collection<ItemLine> itemLines = salesQuotation.getItemLines();
            createNewDeliveryOrder();

            Collection<ItemLine> deliveryOrderItemLine = new ArrayList<ItemLine>();
            for (ItemLine il : itemLines) {
                ItemLine il1 = new ItemLine();
                il1.setMemberDiscount(il.getMemberDiscount());
                il1.setOrderDiscount(il.getOrderDiscount());
                il1.setProduct(il.getProduct());
                il1.setQtyAvailable(il.getQtyAvailable());
                il1.setQtyOrderedBar(il.getQtyOrderedBar());
                il1.setQtyOrderedCase(il.getQtyOrderedCase());
                il1.setSubTotal(il.getSubTotal());
                il1.setTimeCreated(il.getTimeCreated());
                il1.setTotal(il.getTotal());
//                il1.setWarehouse(il.getWarehouse());
                deliveryOrderItemLine.add(il1);
            }
            newDeliveryOrder.setItemLines(deliveryOrderItemLine);
            newDeliveryOrder.setSalesQuotation(salesQuotation);

            ArrayList<DeliveryOrder> dl = new ArrayList<DeliveryOrder>();
            dl.add(newDeliveryOrder);

            salesQuotation.setDeliveryOrders(dl);

        } else { //if partial shipment

            Collection<ItemLine> itemLines = salesQuotation.getItemLines();

            createNewDeliveryOrder();
            createNewDeliveryOrder2();

            Collection<ItemLine> deliveryOrderItemLine = new ArrayList<ItemLine>();
            Collection<ItemLine> deliveryOrderItemLine2 = new ArrayList<ItemLine>();
            for (ItemLine il : itemLines) {

                ItemLine il1 = new ItemLine();
                il1.setMemberDiscount(il.getMemberDiscount());
                il1.setOrderDiscount(il.getOrderDiscount());
                il1.setProduct(il.getProduct());
                il1.setQtyAvailable(il.getQtyAvailable());
                il1.setQtyOrderedBar(il.getQtyOrderedBar());
                il1.setQtyOrderedCase((long) il.getQtyOrderedCase() / (long) 2);
                il1.setSubTotal(il.getSubTotal());
                il1.setTimeCreated(il.getTimeCreated());
                il1.setTotal(il.getTotal());
//                il1.setWarehouse(il.getWarehouse());

                ItemLine il2 = new ItemLine();
                il2.setMemberDiscount(il.getMemberDiscount());
                il2.setOrderDiscount(il.getOrderDiscount());
                il2.setProduct(il.getProduct());
                il2.setQtyAvailable(il.getQtyAvailable());
                il2.setQtyOrderedBar(il.getQtyOrderedBar());
                il2.setQtyOrderedCase((long) il.getQtyOrderedCase() - (long) il1.getQtyOrderedCase());
                il2.setSubTotal(il.getSubTotal());
                il2.setTimeCreated(il.getTimeCreated());
                il2.setTotal(il.getTotal());
                //             il2.setWarehouse(il.getWarehouse());

                deliveryOrderItemLine.add(il1);
                deliveryOrderItemLine2.add(il2);
            }
            newDeliveryOrder.setItemLines(deliveryOrderItemLine);
            newDeliveryOrder2.setItemLines(deliveryOrderItemLine2);
            newDeliveryOrder.setSalesQuotation(salesQuotation);
            newDeliveryOrder2.setSalesQuotation(salesQuotation);

            ArrayList<DeliveryOrder> dl = new ArrayList<DeliveryOrder>();
            dl.add(newDeliveryOrder);
            dl.add(newDeliveryOrder2);
            salesQuotation.setDeliveryOrders(dl);
        }

    }

    private void createNewDeliveryOrder() {
        newDeliveryOrder = new DeliveryOrder();
        newDeliveryOrder.setLeadTime(null);
        newDeliveryOrder.setUrgent(Boolean.FALSE);
        newDeliveryOrder.setItemLines(new ArrayList<ItemLine>());
        newDeliveryOrder.setInvoice(null);
        newDeliveryOrder.setPurchaseOrder(null);
        newDeliveryOrder.setSalesOrder(null);
        newDeliveryOrder.setSalesQuotation(salesQuotation);
        newDeliveryOrder.setActive(false);

        //Add itemline for all products
        Collection<Product> products = sLCSessionBean.getAllProduct();
        for (Product pd : products) {
            ItemLine il = new ItemLine();
//            il.setWarehouse(null);
            il.setProduct(pd);
            newDeliveryOrder.getItemLines().add(il);
        }
    }

    private void createNewDeliveryOrder2() {
        newDeliveryOrder2 = new DeliveryOrder();
        newDeliveryOrder2.setLeadTime(null);
        newDeliveryOrder2.setUrgent(Boolean.FALSE);
        newDeliveryOrder2.setItemLines(new ArrayList<ItemLine>());
        newDeliveryOrder2.setInvoice(null);
        newDeliveryOrder2.setPurchaseOrder(null);
        newDeliveryOrder2.setSalesOrder(null);
        newDeliveryOrder2.setSalesQuotation(salesQuotation);
        newDeliveryOrder2.setActive(false);

        //Add itemline for all products
        Collection<Product> products = sLCSessionBean.getAllProduct();
        for (Product pd : products) {
            ItemLine il = new ItemLine();
//            il.setWarehouse(null);
            il.setProduct(pd);
            newDeliveryOrder2.getItemLines().add(il);
        }
    }

    public Collection<Address> getClientAddress() {
        SalesLead client = null;
        try {
            System.out.println("SAles Quotation client: " + salesQuotation.getClient().getCompanyName());
            client = sLCSessionBean.getClientById(salesQuotation.getClient().getId());
            return client.getShippingAddress();
        } catch (NotExistException ex) {
            System.out.println("Client does not exist: " + ex.getMessage());
        }
        return null;
    }

    public boolean displayItemLine(Long rowIndex) {

        Collection<ItemLine> collection = salesQuotation.getItemLines();
        ArrayList<ItemLine> list = new ArrayList<ItemLine>();
        for (ItemLine il : collection) {
            list.add(il);
        }

        ItemLine il = (ItemLine) list.get(rowIndex.intValue());
        if (il.getQtyOrderedCase() == 0) {
            return false;
        }
        return true;
    }

    private String convertToDateFormat(Timestamp timeStamp) {
        return formatter.format((java.util.Date) timeStamp);
    }

    public String createSalesQuotation() {

        try {
            salesQuotation.setClient(sLCSessionBean.getClientByClientId(salesQuotation.getClient().getClientId()));
            long eightHours = (long) (8 * 60 * 60 * 1000);
            if (date1 != null) {
                newDeliveryOrder.setLeadTimeTS(new Timestamp(date1.getTime() + eightHours));
                System.out.println("Date 1: " + date1.toString() + " " + newDeliveryOrder.getLeadTimeTS().toString());
            } else {
                newDeliveryOrder.setLeadTimeTS(null);
            }

            if (date2 != null && newDeliveryOrder2 != null) {
                newDeliveryOrder2.setLeadTimeTS(new Timestamp(date2.getTime() + eightHours));
                System.out.println("Date 2: " + date2.toString() + " " + newDeliveryOrder2.getLeadTimeTS().toString());
            }
            if (date2 == null && newDeliveryOrder2 != null) {
                newDeliveryOrder2.setLeadTimeTS(null);
            }
        } catch (NotExistException ex) {
            return ex.getMessage();
        }

        // Validate
        boolean valid = true;

        //check indicative lead time
        System.out.println("TS: " + newDeliveryOrder.getIndicativeLeadTime());
        if (newDeliveryOrder.getIndicativeLeadTime().equals("")) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please do the available to promise check and get the lead time", ""));
            valid = false;
        }
        if (newDeliveryOrder2 != null) {
            if (newDeliveryOrder2.getIndicativeLeadTime().equals("")) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please check and get the lead time", ""));
                valid = false;
            }
        }



        for (ItemLine il : salesQuotation.getItemLines()) {
            if (il.getSpecialDiscount() > (double) maxSpecialDiscount) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Special discount cannot be more than " + maxSpecialDiscount, ""));
                valid = false;
            }
        }

        if (!salesQuotation.getFullShipment()) {

            //Check total quantity
            long totalQuantity = (long) 0;
            long salesQuotationQuantity = (long) 0;
            ArrayList<DeliveryOrder> dls = new ArrayList<DeliveryOrder>();
            dls.add(newDeliveryOrder);
            dls.add(newDeliveryOrder2);
            for (DeliveryOrder dl : dls) {
                Collection<ItemLine> ils = dl.getItemLines();
                for (ItemLine il : ils) {
                    totalQuantity += il.getQtyOrderedCase();
                }
            }
            for (ItemLine il : salesQuotation.getItemLines()) {
                salesQuotationQuantity += il.getQtyOrderedCase();
            }
            if (totalQuantity != salesQuotationQuantity) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order quantity does not sum up to total order quantity", ""));
                valid = false;
            }


            //Check minimum quantity
            for (ItemLine il : newDeliveryOrder.getItemLines()) {
                if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                    if (il.getQtyOrderedCase() < 5 && il.getQtyOrderedCase() != 0) {
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order 1: Minimum delivery order for each product is 5", ""));
                        valid = false;
                    }
                } else {//for whole sale customers
                    if (il.getQtyOrderedCase() < 5 && il.getQtyOrderedCase() != 0) {
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order 1: Minimum delivery order for each product is 5", ""));
                        valid = false;
                    }
                }
            }
            for (ItemLine il : newDeliveryOrder2.getItemLines()) {
                if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                    if (il.getQtyOrderedCase() < 5 && il.getQtyOrderedCase() != 0) {
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order 2: Minimum delivery order for each product is 5", ""));
                        valid = false;
                    }
                } else {//for whole sale customers
                    if (il.getQtyOrderedCase() < 5 && il.getQtyOrderedCase() != 0) {
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order 2: Minimum delivery order for each product is 5", ""));
                        valid = false;
                    }
                }
            }
        }


        if (!valid) {
            return null;
        }


        if (salesQuotation.getFullShipment()) { // Full Shipment
            salesQuotation.setDeliveryOrders(new ArrayList<DeliveryOrder>());
            salesQuotation.addDeliveryOrder(newDeliveryOrder);
            newDeliveryOrder.setSalesQuotation(salesQuotation);
        } else { // Partial Shipment
            salesQuotation.setDeliveryOrders(new ArrayList<DeliveryOrder>());
            salesQuotation.addDeliveryOrder(newDeliveryOrder);
            newDeliveryOrder.setSalesQuotation(salesQuotation);
            salesQuotation.addDeliveryOrder(newDeliveryOrder2);
            newDeliveryOrder2.setSalesQuotation(salesQuotation);
        }

        if (salesQuotation.getClient() instanceof Customer) {
            try {
                Customer c1 = sLCSessionBean.getCustomerByClientId(salesQuotation.getClient().getClientId());

                //Get Member Discount
                MemberDiscountGroup memberDiscountGroup = sLCSessionBean.getCustomerMemberDiscountGroup(c1);
                memberDiscount = memberDiscountGroup.getMemberDiscount();
            } catch (Exception e) {
                System.out.println("Exception: " + e.getMessage());
            }
        } else {
            memberDiscount = 0.0;
        }

        double md = memberDiscount;
        double odAmount = (double) 0;
        double mdAmount = (double) 0;
        double sdAmount = (double) 0;
        double originalPrice = (double) 0;
        //Get Order Discount
        ArrayList<ItemLine> totalItemLines = new ArrayList<ItemLine>(salesQuotation.getItemLines());
        for (int i = 0; i < totalItemLines.size(); i++) {
            ItemLine il = totalItemLines.get(i);
            double quantityBar;
            if (il.getProduct().getProductType().contains("Classic")) {
                quantityBar = (double) il.getQtyOrderedCase()*240;
            } else {
                quantityBar = (double) il.getQtyOrderedCase()*200;
            }
            il.setQtyOrderedBar(new Double(quantityBar).longValue());
            orderDiscountGroup = sLCSessionBean.getOrderDiscountGroup(il);
            il.setOrderDiscount(orderDiscountGroup.getOrderDiscount());
            il.setMemberDiscount(memberDiscount);

            //Calculate Subtotal
          if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                if (il.getProduct().getProductType().contains("Classic")){
                il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getDsUnitPrice()*240));
                il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getDsUnitPrice() / 1.2*240));}
                else {
                il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getDsUnitPrice()*200));
                il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getDsUnitPrice() / 1.2*200));
            }
            } else { //WholeSale clients
                if (il.getProduct().getProductType().contains("Classic")) {
                    il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getWsUnitPrice() * 240));
                    il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getWsUnitPrice() / 1.2 * 240));
                } else {
                    il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getWsUnitPrice() * 200));
                    il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getWsUnitPrice() / 1.2 * 200));
                }
            }
          
            double unitPrice;
            if (salesQuotation.getCurrency() == Boolean.TRUE) {
                //SGD
                if (il.getProduct().getProductType().contains("Classic")) {
                    unitPrice = il.getUnitPriceSGD() / 240;
                } else {
                    unitPrice = il.getUnitPriceSGD() / 200;
                }
            } else {
                //USD
                if (il.getProduct().getProductType().contains("Classic")) {
                    unitPrice = il.getUnitPriceUSD() / 240;
                } else {
                    unitPrice = il.getUnitPriceUSD() / 200;
                }

            }
            double od = (double) il.getOrderDiscount();
            double sd = (double) il.getSpecialDiscount();
            itemSubtotal = (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) 1 - (double) md) * ((double) 1 - (double) sd);
            originalPrice = originalPrice + (double) quantityBar * (double) unitPrice;
            odAmount = odAmount + (double) quantityBar * (double) unitPrice * (double) od;
            mdAmount = mdAmount + (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) md);
            sdAmount = sdAmount + (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) 1 - (double) md) * (double) sd;
            //Rounding
            itemSubtotal = roundFourDecimals(itemSubtotal);
            il.setSubTotal(itemSubtotal);
            subtotals.add(itemSubtotal);
            subtotalSum = subtotalSum + itemSubtotal;
            totalItemLines.set(i, il);
        }
        salesQuotation.setItemLines(totalItemLines);
        salesQuotation.setSubtotal(originalPrice);
        salesQuotation.setMemberDiscount(mdAmount);
        salesQuotation.setOrderDiscount(odAmount);
        salesQuotation.setSpecialDiscount(sdAmount);
        salesQuotation.setTotal(subtotalSum);

        //Get Lead Time - Use dummy data first
        Long futureDate;
        Long currentDate = new Date().getTime();
        Collection<DeliveryOrder> orders = new ArrayList<DeliveryOrder>();/*
        if (newDeliveryOrder.getUrgent() == Boolean.TRUE) {
        futureDate = currentDate + 3 * 86400000; //3 days for urgent order
        newDeliveryOrder.setLeadTime(convertToDateFormat(new Timestamp(futureDate)));
        } else {
        futureDate = currentDate + 14 * 86400000; //2 weeks for non-urgent order
        newDeliveryOrder.setLeadTime(convertToDateFormat(new Timestamp(futureDate)));
        }
         */
        orders.add(newDeliveryOrder);
        if (!salesQuotation.getFullShipment()) {/*
            if (newDeliveryOrder2.getUrgent() == Boolean.TRUE) {
            futureDate = currentDate + 3 * 86400000; //3 days for urgent order
            newDeliveryOrder2.setLeadTime(convertToDateFormat(new Timestamp(futureDate)));
            } else {
            futureDate = currentDate + 14 * 86400000; //2 weeks for non-urgent order
            newDeliveryOrder2.setLeadTime(convertToDateFormat(new Timestamp(futureDate)));
            }*/
            orders.add(newDeliveryOrder2);
        }

        salesQuotation.setDeliveryOrders(orders);

        //Set DeliveryOrder to salesquotation
        for (DeliveryOrder dl : orders) {
            dl.setSalesQuotation(salesQuotation);
        }

        //Set SalesQuotation to client and client to SalesQuotation
        SalesLead client = salesQuotation.getClient();
        client.getSalesQuotations().add(salesQuotation);


        // If no comments, write no comments
        if (salesQuotation.getComments().equals("")) {
            salesQuotation.setComments("No additional comments from client");
        }

        // set it as session map attribute
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(SQ, salesQuotation);

        return "createSalesQuotationConfirm?faces-redirect=true";
    }

    public String recalculateSalesQuotation() {
        try {
            salesQuotation.setClient(sLCSessionBean.getClientByClientId(salesQuotation.getClient().getClientId()));
            long eightHours = (long) (8 * 60 * 60 * 1000);
            if (date1 != null) {
                newDeliveryOrder.setLeadTimeTS(new Timestamp(date1.getTime() + eightHours));
                System.out.println("Date 1: " + date1.toString() + " " + newDeliveryOrder.getLeadTimeTS().toString());
            } else {
                newDeliveryOrder.setLeadTimeTS(null);
            }

            if (date2 != null && newDeliveryOrder2 != null) {
                newDeliveryOrder2.setLeadTimeTS(new Timestamp(date2.getTime() + eightHours));
                System.out.println("Date 2: " + date2.toString() + " " + newDeliveryOrder2.getLeadTimeTS().toString());
            }
            if (date2 == null && newDeliveryOrder2 != null) {
                newDeliveryOrder2.setLeadTimeTS(null);
            }
          }  catch (NotExistException ex) {
            return ex.getMessage();
        }

        // Validate
        boolean valid = true;

        for (ItemLine il : salesQuotation.getItemLines()) {
            if (il.getSpecialDiscount() > (double) maxSpecialDiscount) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Special discount cannot be more than " + maxSpecialDiscount, ""));
                valid = false;
            }
        }

        if (!salesQuotation.getFullShipment()) {

            //Check total quantity
            long totalQuantity = (long) 0;
            long salesQuotationQuantity = (long) 0;
            ArrayList<DeliveryOrder> dls = new ArrayList<DeliveryOrder>();
            dls.add(newDeliveryOrder);
            dls.add(newDeliveryOrder2);
            for (DeliveryOrder dl : dls) {
                Collection<ItemLine> ils = dl.getItemLines();
                for (ItemLine il : ils) {
                    totalQuantity += il.getQtyOrderedCase();
                }
            }
            for (ItemLine il : salesQuotation.getItemLines()) {
                salesQuotationQuantity += il.getQtyOrderedCase();
            }
            if (totalQuantity != salesQuotationQuantity) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order quantity does not sum up to total order quantity", ""));
                valid = false;
            }

            //Check minimum quantity
            for (ItemLine il : newDeliveryOrder.getItemLines()) {
                if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                    if (il.getQtyOrderedCase() < 5 && il.getQtyOrderedCase() != 0) {
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order 1: Minimum delivery order for each product is 5", ""));
                        valid = false;
                    }
                } else {//for whole sale customers
                    if (il.getQtyOrderedCase() < 5 && il.getQtyOrderedCase() != 0) {
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order 1: Minimum delivery order for each product is 5", ""));
                        valid = false;
                    }
                }
            }
            for (ItemLine il : newDeliveryOrder2.getItemLines()) {
                if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                    if (il.getQtyOrderedCase() < 5 && il.getQtyOrderedCase() != 0) {
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order 2: Minimum delivery order for each product is 5", ""));
                        valid = false;
                    }
                } else {//for whole sale customers
                    if (il.getQtyOrderedCase() < 5 && il.getQtyOrderedCase() != 0) {
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Delivery Order 2: Minimum delivery order for each product is 5", ""));
                        valid = false;
                    }
                }
            }
        }


        if (!valid) {
            return null;
        }

        //TO DO: match sales quotation with purchase order

        if (salesQuotation.getFullShipment()) { // Full Shipment
            salesQuotation.addDeliveryOrder(newDeliveryOrder);
            newDeliveryOrder.setSalesQuotation(salesQuotation);
        } else { // Partial Shipment
            salesQuotation.addDeliveryOrder(newDeliveryOrder);
            newDeliveryOrder.setSalesQuotation(salesQuotation);
            salesQuotation.addDeliveryOrder(newDeliveryOrder2);
            newDeliveryOrder2.setSalesQuotation(salesQuotation);
        }

        if (salesQuotation.getClient() instanceof Customer) {
            try {
                Customer c1 = sLCSessionBean.getCustomerByClientId(salesQuotation.getClient().getClientId());

                //Get Member Discount
                MemberDiscountGroup memberDiscountGroup = sLCSessionBean.getCustomerMemberDiscountGroup(c1);
                memberDiscount = memberDiscountGroup.getMemberDiscount();
            } catch (Exception e) {
                System.out.println("Exception: " + e.getMessage());
            }
        } else {
            memberDiscount = 0.0;
        }

        double md = memberDiscount;
        double odAmount = (double) 0;
        double mdAmount = (double) 0;
        double sdAmount = (double) 0;
        double originalPrice = (double) 0;
        //Get Order Discount
        ArrayList<ItemLine> totalItemLines = new ArrayList<ItemLine>(salesQuotation.getItemLines());
        for (int i = 0; i < totalItemLines.size(); i++) {
            ItemLine il = totalItemLines.get(i);
            double quantityBar;
            if (il.getProduct().getProductType().contains("Classic")) {
                quantityBar = (double) il.getQtyOrderedCase() * 240;
            } else {
                quantityBar = (double) il.getQtyOrderedCase() * 200;
            }
            il.setQtyOrderedBar(new Double(quantityBar).longValue());
            orderDiscountGroup = sLCSessionBean.getOrderDiscountGroup(il);
            il.setOrderDiscount(orderDiscountGroup.getOrderDiscount());
            il.setMemberDiscount(memberDiscount);

            //Calculate Subtotal
             if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                if (il.getProduct().getProductType().contains("Classic")){
                il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getDsUnitPrice()*240));
                il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getDsUnitPrice() / 1.2*240));}
                else {
                il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getDsUnitPrice()*200));
                il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getDsUnitPrice() / 1.2*200));
            }
            } else { //WholeSale clients
                if (il.getProduct().getProductType().contains("Classic")) {
                    il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getWsUnitPrice() * 240));
                    il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getWsUnitPrice() / 1.2 * 240));
                } else {
                    il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getWsUnitPrice() * 200));
                    il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getWsUnitPrice() / 1.2 * 200));
                }
            }
            double unitPrice;
            if (salesQuotation.getCurrency() == Boolean.TRUE) {
                //SGD
                if (il.getProduct().getProductType().contains("Classic")) {
                    unitPrice = il.getUnitPriceSGD() / 240;
                } else {
                    unitPrice = il.getUnitPriceSGD() / 200;
                }
            } else {
                //USD
                if (il.getProduct().getProductType().contains("Classic")) {
                    unitPrice = il.getUnitPriceUSD() / 240;
                } else {
                    unitPrice = il.getUnitPriceUSD() / 200;
                }

            }
            double od = (double) il.getOrderDiscount();
            double sd = (double) il.getSpecialDiscount();
            itemSubtotal = (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) 1 - (double) md) * ((double) 1 - (double) sd);
            originalPrice = originalPrice + (double) quantityBar * (double) unitPrice;
            odAmount = odAmount + (double) quantityBar * (double) unitPrice * (double) od;
            mdAmount = mdAmount + (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) md);
            sdAmount = sdAmount + (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) 1 - (double) md) * (double) sd;
            //Rounding
            itemSubtotal = roundFourDecimals(itemSubtotal);
            il.setSubTotal(itemSubtotal);
            subtotals.add(itemSubtotal);
            subtotalSum = subtotalSum + itemSubtotal;
            totalItemLines.set(i, il);
        }
        salesQuotation.setItemLines(totalItemLines);
        salesQuotation.setSubtotal(originalPrice);
        salesQuotation.setMemberDiscount(mdAmount);
        salesQuotation.setOrderDiscount(odAmount);
        salesQuotation.setSpecialDiscount(sdAmount);
        salesQuotation.setTotal(subtotalSum);


        //Get Lead Time - Use dummy data first
        Long futureDate;
        Long currentDate = new Date().getTime();
        Collection<DeliveryOrder> orders = new ArrayList<DeliveryOrder>();
        /*  if (newDeliveryOrder.getUrgent() == Boolean.TRUE) {
        futureDate = currentDate + 3 * 86400000; //3 days for urgent order
        newDeliveryOrder.setLeadTime(convertToDateFormat(new Timestamp(futureDate)));
        } else {
        futureDate = currentDate + 14 * 86400000; //2 weeks for non-urgent order
        newDeliveryOrder.setLeadTime(convertToDateFormat(new Timestamp(futureDate)));
        }*/
        orders.add(newDeliveryOrder);
        if (newDeliveryOrder2 != null) {/*
            if (newDeliveryOrder2.getUrgent() == Boolean.TRUE) {
            futureDate = currentDate + 3 * 86400000; //3 days for urgent order
            newDeliveryOrder2.setLeadTime(convertToDateFormat(new Timestamp(futureDate)));
            } else {
            futureDate = currentDate + 14 * 86400000; //2 weeks for non-urgent order
            newDeliveryOrder2.setLeadTime(convertToDateFormat(new Timestamp(futureDate)));
            }*/
            orders.add(newDeliveryOrder2);
        }

        salesQuotation.setDeliveryOrders(orders);

        //Set DeliveryOrder to salesquotation
        for (DeliveryOrder dl : orders) {
            dl.setSalesQuotation(salesQuotation);
        }

        //Set SalesQuotation to client and client to SalesQuotation
        SalesLead client = salesQuotation.getClient();
        client.getSalesQuotations().add(salesQuotation);


        // If no comments, write no comments
        if (salesQuotation.getComments().equals("")) {
            salesQuotation.setComments("No additional comments from client");
        }
        // set it as session map attribute
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(SQ, salesQuotation);
        return "viewSalesQuotationEditConfirm?faces-redirect=true";

    }

    public String confirmSalesQuotation() {
        SalesQuotation sq = sOPSessionBean.saveSalesQuotation(salesQuotation);
        if (sq != null) {
            result = "Sales Quotation of ID " + sq.getId() + " , Sales Quotation Number " + sq.getSqNumber() + " saved successfully.";
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(RESULT1, result);
            return "viewSalesQuotationStatus?faces-redirect=true";
        } else {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Sales Quotation didn't saved successfully", "Sales Quotation didn't saved successfully."));
            return null;
        }
    }
    
    public String confirmEditSalesQuotation(){
        SalesQuotation sq = sOPSessionBean.saveEditSalesQuotation(salesQuotation);
        if (sq != null) {
            result = "Sales Quotation of ID " + sq.getId() + " , Sales Quotation Number " + sq.getSqNumber() + " saved successfully.";
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(RESULT1, result);
            return "viewSalesQuotationStatus?faces-redirect=true";
        } else {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Sales Quotation didn't saved successfully", "Sales Quotation didn't saved successfully."));
            return null;
        }
    }
    public String sendSalesQuotation() {
        salesQuotation.setSentToCustomer(true);
        //TODO: Email to customer!
        // ?? do you need to save the status of "senttocustomer"?
        
        // edited by ZY, 9 Nov 2011
        String res = "Sales Quotation sent to customer";
        String emailAddress = "";
        
        if (salesQuotation.getClient().getContactRecords() == null || salesQuotation.getClient().getContactRecords().isEmpty()){
            res = "Sales quotation is not able to sent to customer because no contact record is found.";
        } else {
            emailAddress = new ArrayList<ContactRecord>(salesQuotation.getClient().getContactRecords()).get(0).getEmail();
            fileManagerBean.sendSalesQuotation(emailAddress, salesQuotation.getId());
            System.out.println("email address: "+emailAddress);
        }
        
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(SQ, salesQuotation);
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(RESULT1, res);
        return "viewSalesQuotationDisplay?faces-redirect=true";
    }

    public String cancelSalesQuotation() {
        // FacesContext.getCurrentInstance().addMessage(null,
        // new FacesMessage(FacesMessage.SEVERITY_ERROR, "Purchase Order creation cancelled", "Purchase Order creation cancelled"));
        result = "Sales Quotation cancelled and has not been saved.";
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(RESULT1, result);
        return "viewSalesQuotationStatus?faces-redirect=true";
    }

    public String displaySalesQuotation() {
        try {
            salesQuotation = sOPSessionBean.getSalesQuotationById(salesQuotation.getSqNumber());
        } catch (NotExistException e) {
            //TO DO: Handle exceptions
        }
        salesLead = salesQuotation.getClient();

        boolean currencyBoolean = salesQuotation.getCurrency();
        if (currencyBoolean == Boolean.TRUE) {
            currency = "SGD";
        } else {
            currency = "USD";
        }
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(SQ, salesQuotation);
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(CUR, currency);
        return "viewSalesQuotationDisplay?faces-redirect=true";
    }

    public String updateSalesQuotation() {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(SQ, salesQuotation);
        return "viewSalesQuotationEdit?faces-redirect=true";
    }

    public String cancelEditSQ() {
        result = "Sales Quotation " + salesQuotation.getSqNumber() + " cancel edit.";
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(RESULT1, result);
        return "viewSalesQuotationStatus?faces-redirect=true";
    }

    public String closeSalesQuotation() {
        setResult("Sales Quotation " + salesQuotation.getSqNumber() + " closed.");
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(RESULT1, result);
        return "viewSalesQuotationStatus?faces-redirect=true";
    }

    public String next() {

        //Validate
        //Validation: One orderline should have at least one itemline
        boolean valid1 = true;
        boolean valid2 = true;
        boolean valid3 = true;
        int count = 0;
        for (ItemLine il : salesQuotation.getItemLines()) {
            if (il.getQtyOrderedCase() == 0) {
                count++;
            }
        }
        if (count == 4) {
            valid1 = false;
        }

        if (!valid1) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Order Items cannot be empty", ""));
            return null;
        }

        for (ItemLine il : salesQuotation.getItemLines()) {
            if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                if (il.getQtyOrderedCase() < 10 && il.getQtyOrderedCase() != 0) {
                    valid2 = false;
                }
            } else {//for whole sale customers
                if (il.getQtyOrderedCase() < 50 && il.getQtyOrderedCase() != 0) {
                    valid3 = false;
                }
            }
        }
        if (!valid2) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Minimum order amount for direct sale customers: 10 cases!", ""));
        }
        if (!valid3) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Minimum order amount for whole sale customers: 50 cases!", ""));
        }

        if (!valid2 || !valid3) {
            return null;
        }


        //----------------------------------------------------------------------
        //                          Calculate ItemLines
        //----------------------------------------------------------------------
        if (salesQuotation.getClient() instanceof Customer) {
            try {
                Customer c1 = sLCSessionBean.getCustomerByClientId(salesQuotation.getClient().getClientId());

                //Get Member Discount
                MemberDiscountGroup memberDiscountGroup = sLCSessionBean.getCustomerMemberDiscountGroup(c1);
                memberDiscount = memberDiscountGroup.getMemberDiscount();
            } catch (Exception e) {
                System.out.println("Exception: " + e.getMessage());
            }
        } else {
            memberDiscount = 0.0;
        }

        double md = memberDiscount;
        double odAmount = (double) 0;
        double mdAmount = (double) 0;
        double sdAmount = (double) 0;
        double originalPrice = (double) 0;
        //Get Order Discount
        ArrayList<ItemLine> totalItemLines = new ArrayList<ItemLine>(salesQuotation.getItemLines());
        for (int i = 0; i < totalItemLines.size(); i++) {
            ItemLine il = totalItemLines.get(i);
            double quantityBar;
            if (il.getProduct().getProductType().contains("Classic")) {
                quantityBar = (double) il.getQtyOrderedCase() * 240;
            } else {
                quantityBar = (double) il.getQtyOrderedCase() * 200;
            }
            il.setQtyOrderedBar(new Double(quantityBar).longValue());
            orderDiscountGroup = sLCSessionBean.getOrderDiscountGroup(il);
            il.setOrderDiscount(orderDiscountGroup.getOrderDiscount());
            il.setMemberDiscount(memberDiscount);

            //Calculate Subtotal
           if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                if (il.getProduct().getProductType().contains("Classic")){
                il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getDsUnitPrice()*240));
                il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getDsUnitPrice() / 1.2*240));}
                else {
                il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getDsUnitPrice()*200));
                il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getDsUnitPrice() / 1.2*200));
            }
            } else { //WholeSale clients
                if (il.getProduct().getProductType().contains("Classic")) {
                    il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getWsUnitPrice() * 240));
                    il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getWsUnitPrice() / 1.2 * 240));
                } else {
                    il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getWsUnitPrice() * 200));
                    il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getWsUnitPrice() / 1.2 * 200));
                }
            }
            double unitPrice;
            if (salesQuotation.getCurrency() == Boolean.TRUE) {
                //SGD
                if (il.getProduct().getProductType().contains("Classic")) {
                    unitPrice = il.getUnitPriceSGD() / 240;
                } else {
                    unitPrice = il.getUnitPriceSGD() / 200;
                }
            } else {
                //USD
                if (il.getProduct().getProductType().contains("Classic")) {
                    unitPrice = il.getUnitPriceUSD() / 240;
                } else {
                    unitPrice = il.getUnitPriceUSD() / 200;
                }

            }
            double od = (double) il.getOrderDiscount();
            double sd = (double) il.getSpecialDiscount();
            itemSubtotal = (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) 1 - (double) md) * ((double) 1 - (double) sd);
            originalPrice = originalPrice + (double) quantityBar * (double) unitPrice;
            odAmount = odAmount + (double) quantityBar * (double) unitPrice * (double) od;
            mdAmount = mdAmount + (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) md);
            sdAmount = sdAmount + (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) 1 - (double) md) * (double) sd;
            //Rounding
            itemSubtotal = roundFourDecimals(itemSubtotal);
            il.setSubTotal(itemSubtotal);
            subtotals.add(itemSubtotal);
            subtotalSum = subtotalSum + itemSubtotal;
            totalItemLines.set(i, il);
        }

        setDeliveryOrder();
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(SQ, salesQuotation);
        return "createSalesQuotationNext?faces-redirect=true";
    }

    public String editNext() {
        //Validate
        //Validation: One orderline should have at least one itemline
        boolean valid1 = true;
        boolean valid2 = true;
        boolean valid3 = true;
        
//        if(!validateAddress()){
//            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please fill in the address information completely", ""));
//            return null;
//        }
//        
        
        int count = 0;
        for (ItemLine il : salesQuotation.getItemLines()) {
            if (il.getQtyOrderedCase() == 0) {
                count++;
            }
        }
        if (count == 4) {
            valid1 = false;
        }

        if (!valid1) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Order Items cannot be empty", ""));
            return null;
        }

        for (ItemLine il : salesQuotation.getItemLines()) {
            if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                if (il.getQtyOrderedCase() < 10 && il.getQtyOrderedCase() != 0) {
                    valid2 = false;
                }
            } else {//for whole sale customers
                if (il.getQtyOrderedCase() < 50 && il.getQtyOrderedCase() != 0) {
                    valid3 = false;
                }
            }
        }
        if (!valid2) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Minimum order amount for direct sale customers: 10 cases!", ""));
        }
        if (!valid3) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Minimum order amount for whole sale customers: 50 cases!", ""));
        }

        if (!valid2 || !valid3) {
            return null;
        }


        //----------------------------------------------------------------------
        //                          Calculate ItemLines
        //----------------------------------------------------------------------
        if (salesQuotation.getClient() instanceof Customer) {
            try {
                Customer c1 = sLCSessionBean.getCustomerByClientId(salesQuotation.getClient().getClientId());

                //Get Member Discount
                MemberDiscountGroup memberDiscountGroup = sLCSessionBean.getCustomerMemberDiscountGroup(c1);
                memberDiscount = memberDiscountGroup.getMemberDiscount();
            } catch (Exception e) {
                System.out.println("Exception: " + e.getMessage());
            }
        } else {
            memberDiscount = 0.0;
        }

        double md = memberDiscount;
        double odAmount = (double) 0;
        double mdAmount = (double) 0;
        double sdAmount = (double) 0;
        double originalPrice = (double) 0;
        //Get Order Discount
        ArrayList<ItemLine> totalItemLines = new ArrayList<ItemLine>(salesQuotation.getItemLines());
        for (int i = 0; i < totalItemLines.size(); i++) {
            ItemLine il = totalItemLines.get(i);
            double quantityBar;
            if (il.getProduct().getProductType().contains("Classic")) {
                quantityBar = (double) il.getQtyOrderedCase() * 240;
            } else {
                quantityBar = (double) il.getQtyOrderedCase() * 200;
            }
            il.setQtyOrderedBar(new Double(quantityBar).longValue());
            orderDiscountGroup = sLCSessionBean.getOrderDiscountGroup(il);
            il.setOrderDiscount(orderDiscountGroup.getOrderDiscount());
            il.setMemberDiscount(memberDiscount);

            //Calculate Subtotal
             if (salesQuotation.getClient().getCategory().equals("DirectSale")) {
                if (il.getProduct().getProductType().contains("Classic")){
                il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getDsUnitPrice()*240));
                il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getDsUnitPrice() / 1.2*240));}
                else {
                il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getDsUnitPrice()*200));
                il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getDsUnitPrice() / 1.2*200));
            }
            } else { //WholeSale clients
                if (il.getProduct().getProductType().contains("Classic")) {
                    il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getWsUnitPrice() * 240));
                    il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getWsUnitPrice() / 1.2 * 240));
                } else {
                    il.setUnitPriceSGD(roundFourDecimals(il.getProduct().getWsUnitPrice() * 200));
                    il.setUnitPriceUSD(roundFourDecimals(il.getProduct().getWsUnitPrice() / 1.2 * 200));
                }
            }
            double unitPrice;
            if (salesQuotation.getCurrency() == Boolean.TRUE) {
                //SGD
                if (il.getProduct().getProductType().contains("Classic")) {
                    unitPrice = il.getUnitPriceSGD() / 240;
                } else {
                    unitPrice = il.getUnitPriceSGD() / 200;
                }
            } else {
                //USD
                if (il.getProduct().getProductType().contains("Classic")) {
                    unitPrice = il.getUnitPriceUSD() / 240;
                } else {
                    unitPrice = il.getUnitPriceUSD() / 200;
                }

            }
            double od = (double) il.getOrderDiscount();
            double sd = (double) il.getSpecialDiscount();
            itemSubtotal = (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) 1 - (double) md) * ((double) 1 - (double) sd);
            originalPrice = originalPrice + (double) quantityBar * (double) unitPrice;
            odAmount = odAmount + (double) quantityBar * (double) unitPrice * (double) od;
            mdAmount = mdAmount + (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) md);
            sdAmount = sdAmount + (double) quantityBar * (double) unitPrice * ((double) 1.0 - (double) od) * ((double) 1 - (double) md) * (double) sd;
            //Rounding
            itemSubtotal = roundFourDecimals(itemSubtotal);
            il.setSubTotal(itemSubtotal);
            subtotals.add(itemSubtotal);
            subtotalSum = subtotalSum + itemSubtotal;
            totalItemLines.set(i, il);
        }

        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(SQ, salesQuotation);
        return "viewSalesQuotationEditNext?faces-redirect=true";
    }

    public void addShippingAddress() {

        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;

        // Address Line 1: Required
        if (!isNotEmpty(newAddress.getAddressLine1())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Line 1", "cannot be empty."));
            valid = false;
        }

        // Zipcode: Numeric, Required
        if (!isNotEmpty(newAddress.getZipCode())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Zip Code", "cannot be empty."));
            valid = false;
        }
        if (!isNumeric(newAddress.getZipCode())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Zip Code", "can only contain numeric characters."));
            valid = false;
        }

        // City: Alphabetic, Required
        if (!isNotEmpty(newAddress.getCity())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address City", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(newAddress.getCity())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address City", "can only contain alphabetical characters."));
            valid = false;
        }

        // State: Alphabetic, Required
        if (!isNotEmpty(newAddress.getStateName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address State", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(newAddress.getStateName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address State", "can only contain alphabetical characters."));
            valid = false;
        }

        //Country: Alphabetic, Required
        if (!isNotEmpty(newAddress.getCountry())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Country", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(newAddress.getCountry())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Country", "can only contain alphabetical characters."));
            valid = false;
        }

        context.addCallbackParam("valid", valid);

        if (valid) {
            SalesLead client = salesQuotation.getClient();
            client.getShippingAddress().add(newAddress);
            client = sLCSessionBean.updateSalesLead(client);
            salesQuotation.setClient(client);

            //Reset shipping address
            newAddress = new Address();
        }
    }

    public void aTPCheck1() {
        DeliveryOrder deliveryOrder = newDeliveryOrder;
        //TODO: edited by zy
        if (newDeliveryOrder == null) {
            return;
        }
        if (newDeliveryOrder.getUrgent()) {
            newDeliveryOrder.setIndicativeLeadTime(atpSessionBean.getIndicativeLeadTimeforUrgent(deliveryOrder, new Timestamp(date1.getTime())));
        } else {
            newDeliveryOrder.setIndicativeLeadTimeTS(atpSessionBean.getIndicativeLeadTimeForRFQ(deliveryOrder));
            if (newDeliveryOrder.getIndicativeLeadTimeTS() != null) {
                newDeliveryOrder.setIndicativeLeadTime(formatter.format(newDeliveryOrder.getIndicativeLeadTimeTS()));
            } else {
                newDeliveryOrder.setIndicativeLeadTime("Not able to fulfill");
            }
        }
    }

    public void aTPCheck2() {
        DeliveryOrder deliveryOrder = newDeliveryOrder2;
        if (newDeliveryOrder2 != null) {

            if (newDeliveryOrder2.getUrgent()) {
                newDeliveryOrder2.setIndicativeLeadTime(atpSessionBean.getIndicativeLeadTimeforUrgent(deliveryOrder, new Timestamp(date2.getTime())));
            } else {
                newDeliveryOrder2.setIndicativeLeadTimeTS(atpSessionBean.getIndicativeLeadTimeForRFQ(deliveryOrder));
                if(newDeliveryOrder2.getIndicativeLeadTimeTS()==null) {
                    newDeliveryOrder2.setIndicativeLeadTime(Consts.ATP_SO_FAIL);
                }
                else {
                newDeliveryOrder2.setIndicativeLeadTime(formatter.format(newDeliveryOrder2.getIndicativeLeadTimeTS()));
                }
            }
        }
    }

    //-------------------------------------------------------------------------
    //              SalesLeadManager Bean Customer Validator
    //-------------------------------------------------------------------------
    private boolean isValidEmailAddress(String email) {
        if (email.matches("[\\w\\.-]*[a-zA-Z0-9_]@[\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]")) {
            return true;
        }
        return false;
    }

    private boolean isAlphabetic(String str) {
        if (str.matches("[a-zA-Z\\s]*")) {
            return true;
        } else {
            return false;
        }
    }

    private boolean isAlphanumeric(String str) {

        if (str.matches("[a-zA-z0-9\\s]*")) {
            return true;
        } else {
            return false;
        }

    }

    private boolean isNumeric(String str) {
        if (str.matches("[0-9]*")) {
            return true;
        } else {
            return false;
        }

    }

    private boolean isNotEmpty(String str) {
        if (str == null) {
            return false;
        }
        if (str.equals("")) {
            return false;
        }
        return true;
    }

    //--------------------------------------------------------------------------
    //                          Getter and Setter
    //--------------------------------------------------------------------------
    public SalesQuotation getSalesQuotation() {

        SalesQuotation sq = (SalesQuotation) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(SQ);
        if (sq != null) {
            System.out.println("get 122");
            salesQuotation = sq;
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(SQ);
        }
        return salesQuotation;
    }

    public void setSalesQuotation(SalesQuotation salesQuotation) {
        this.salesQuotation = salesQuotation;
        this.sqNumber = salesQuotation.getSqNumber();
    }

    public Address getNewAddress() {
        return newAddress;
    }

    public void setNewAddress(Address newAddress) {
        this.newAddress = newAddress;
    }

    public DeliveryOrder getNewDeliveryOrder() {
        DeliveryOrder dOrder = (DeliveryOrder) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(NEWORDER);
        if (dOrder != null) {
            newDeliveryOrder = dOrder;
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(NEWORDER);
        }
        return newDeliveryOrder;
    }

    public void setNewDeliveryOrder(DeliveryOrder newDeliveryOrder) {
        this.newDeliveryOrder = newDeliveryOrder;
    }

    public ItemLine getNewItemLine() {
        return newItemLine;
    }

    public void setNewItemLine(ItemLine newItemLine) {
        this.newItemLine = newItemLine;
    }

    public DeliveryOrder getSelectedDeliveryOrder() {
        return selectedDeliveryOrder;
    }

    public void setSelectedDeliveryOrder(DeliveryOrder selectedDeliveryOrder) {
        this.selectedDeliveryOrder = selectedDeliveryOrder;
    }

    public boolean isUpdateMode() {
        return updateMode;
    }

    public void setUpdateMode(boolean updateMode) {
        this.updateMode = updateMode;
    }

    public String getLeadTime() {
        return leadTime;
    }

    public void setLeadTime(String leadTime) {
        this.leadTime = leadTime;
    }

    public void setCurrency(String currency) {
        this.currency = currency;
    }

    public String getCurrency() {
        String c = (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(CUR);
        if (c != null) {
            currency = c;
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(CUR);
        }
        return currency;
    }

    public SalesLead getSalesLead() {
        return salesLead;
    }

    public void setSalesLead(SalesLead salesLead) {
        this.salesLead = salesLead;
    }

    public Collection<OrderDiscountGroup> getOrderDiscountGroups() {
        return orderDiscountGroups;
    }

    public void setOrderDiscountGroups(Collection<OrderDiscountGroup> orderDiscountGroups) {
        this.orderDiscountGroups = orderDiscountGroups;
    }

    public Double getSubtotal() {
        return subtotal;
    }

    public void setSubtotal(Double subtotal) {
        this.subtotal = subtotal;
    }

    public Double getSubtotalSumDisplay() {
        return subtotalSumDisplay;
    }

    public void setSubtotalSumDisplay(Double subtotalSumDisplay) {
        this.subtotalSumDisplay = subtotalSumDisplay;
    }

    public Double getTotalDisplay() {
        return totalDisplay;
    }

    public void setTotalDisplay(Double totalDisplay) {
        this.totalDisplay = totalDisplay;
    }

    public Double getItemSubtotalDisplay() {
        return itemSubtotalDisplay;
    }

    public void setItemSubtotalDisplay(Double itemSubtotalDisplay) {
        this.itemSubtotalDisplay = itemSubtotalDisplay;
    }

    public String getRfqNumber() {
        return rfqNumber;
    }

    public void setRfqNumber(String rfqNumber) {
        this.rfqNumber = rfqNumber;
    }

    public String getResult() {
        String r = (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(RESULT1);
        System.out.println("debugging" + r);
        if (r != null) {
            result = r;
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(RESULT1);
        }
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public String getSqNumber() {
        return sqNumber;
    }

    public void setSqNumber(String sqNumber) {
        this.sqNumber = sqNumber;
    }

    public DeliveryOrder getNewDeliveryOrder2() {
        DeliveryOrder dOrder2 = (DeliveryOrder) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(NEWORDER2);
        if (dOrder2 != null) {
            newDeliveryOrder2 = dOrder2;
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(NEWORDER2);
        }
        return newDeliveryOrder2;
    }

    public void setNewDeliveryOrder2(DeliveryOrder newDeliveryOrder2) {
        this.newDeliveryOrder2 = newDeliveryOrder2;
    }

    public Date getDate1() {
        return date1;
    }

    public void setDate1(Date date1) {
        this.date1 = date1;
    }

    public Date getDate2() {
        return date2;
    }

    public void setDate2(Date date2) {
        this.date2 = date2;
    }

    public FileUploadManagerBean getFileManagerBean() {
        return fileManagerBean;
    }

    public void setFileManagerBean(FileUploadManagerBean fileManagerBean) {
        this.fileManagerBean = fileManagerBean;
    }
}
